/*
 * @Author: shanghongyun 2879455630@qq.com
 * @Date: 2025-06-28 14:25:40
 * @LastEditors: shanghongyun 2879455630@qq.com
 * @LastEditTime: 2025-08-07 10:09:06
 * @FilePath: \A06\Device\ADC.c
 * @Description: ADC配置
 */


#include "dev.h"
#include "charger.h"


void delay_us(uint32_t us){
    uint32_t cnt = us * 12;   
    while(cnt--){
        ;
    }
}


//ADC端口配置
static void adc_gpio_config(void){
    GPIO_InitTypeStruct ADC_GPIO_InitStruct;
    GPIO_StructInit(&ADC_GPIO_InitStruct);
    ADC_GPIO_InitStruct.GPIO_Mode = GPIO_MODE_ANALOG;
    ADC_GPIO_InitStruct.GPIO_Speed = GPIO_SPEED_HIGH;
    ADC_GPIO_InitStruct.GPIO_PuPd = GPIO_PUPD_NOPULL;
    ADC_GPIO_InitStruct.GPIO_Pin = BAT_L_VOL_PIN;
    GPIO_Init(GPIOA, &ADC_GPIO_InitStruct);

    ADC_GPIO_InitStruct.GPIO_Pin = BAT_R_VOL_PIN;
    GPIO_Init(GPIOA, &ADC_GPIO_InitStruct);

    ADC_GPIO_InitStruct.GPIO_Pin = PCB_TEMP_PIN;
    GPIO_Init(GPIOD, &ADC_GPIO_InitStruct);

    ADC_GPIO_InitStruct.GPIO_Pin = VIN_PIN;
    GPIO_Init(GPIOD, &ADC_GPIO_InitStruct);

    GPIO_AnaAFConfig(GPIOA, BAT_L_VOL_PIN, GPIO_ANA_AF_0);
    GPIO_AnaAFConfig(GPIOA, BAT_R_VOL_PIN, GPIO_ANA_AF_0);
    GPIO_AnaAFConfig(GPIOD, PCB_TEMP_PIN, GPIO_ANA_AF_0);
    GPIO_AnaAFConfig(GPIOD, VIN_PIN, GPIO_ANA_AF_0);
}

uint8_t gADCconvertPos = 0;
uint8_t gADCconvertSeq[] = {BAT_L_CUR_CHANNEL, BAT_R_CUR_CHANNEL, BAT_L_VOL_CHANNEL, 
                            BAT_R_VOL_CHANNEL, PCB_TEMP_CHANNEL, VIN_CHANNEL};

uint8_t adcChannelMap[] = {BAT_L_CUR_CHANNEL, BAT_R_CUR_CHANNEL, BAT_L_VOL_CHANNEL, 
                            BAT_R_VOL_CHANNEL, PCB_TEMP_CHANNEL, VIN_CHANNEL};
#define ChanleNum     6

#define ADC_CONFIG_MODE0        0
#define ADC_CONFIG_MODE1        1
#define ADC_CONFIG_MODE2        2
#define ADC_CONFIG_MODE         ADC_CONFIG_MODE0


/* Config ADC common parameters */
ADCCOM_InitTypeStruct ADCCOM_InitStruct;
ADCCOM_ChannelStruct ADCCOM_ChannelConfigStruct;
ADC_InitTypeStruct ADC_InitStruct;
ADC_ChannelStruct ADC_ChannelConfigStruct;
#if(ADC_CONFIG_MODE == ADC_CONFIG_MODE0)
/**
 * @description: ADC配置
 * @return {*}
 */
void adc_config(void){
    /*ADC端口配置*/
    adc_gpio_config();
    
    /* Config ADC common parameters */
    ADCCOM_StructInit(&ADCCOM_InitStruct);
    ADCCOM_InitStruct.AdcSpeed = 1;
    ADCCOM_InitStruct.Vref = ADC_VREF_BANDGAP;
    ADCCOM_InitStruct.ClkDiv = ADC_CLK_DIV1;
    ADCCOM_InitStruct.SampleTime0 = ADC_SAMPLE_TIME_288Cycles;
    ADCCOM_InitStruct.SampleTime1 = ADC_SAMPLE_TIME_288Cycles;
    ADCCOM_InitStruct.SampleAccuracy = ADC_Sample_Accuracy_12Bit;
    ADCCOM_InitStruct.IN15Sel = ADC_IN15_SEL_TEMP;
    ADCCOM_InitStruct.PGASel = ADC_PGA_SEL_ALL;
    ADCCOM_Init(&ADCCOM_InitStruct);
    ADCCOM_ChannelStructInit(&ADCCOM_ChannelConfigStruct);

    for(uint8_t i = 0; i < ChanleNum; i++)
    {
        ADCCOM_ChannelConfigStruct.Channel = adcChannelMap[i];
        ADCCOM_ChannelConfigStruct.OversampleEnable = DISABLE;
        ADCCOM_ChannelConfigStruct.SampleTimeSel = ADC_SAMPLE_TIME_SEL0;
        ADCCOM_ChannelConfigStruct.Offset = 0;
        ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);
        
        ADC_ChannelStructInit(&ADC_ChannelConfigStruct);
        ADC_ChannelConfigStruct.Channel = adcChannelMap[i];
        ADC_ChannelConfigStruct.DataAlign = ADC_DATA_ALIGN_RIGHT;
        ADC_ChannelConfigStruct.DataSign = ADC_DATA_UNSIGNED;
        ADC_ChannelConfig(ADC0, &ADC_ChannelConfigStruct);

        ADC_ScanChannelConfig(ADC0 , i , adcChannelMap[i]);
    }

    /* Config ADC0 */
    ADC_StructInit(&ADC_InitStruct);
    ADC_InitStruct.TrigMode = ADC_TRIG_SW_SINGLE_SEQ_CONV;  //单次扫描
    ADC_InitStruct.ContinueWait = ADC_CONTINUE_WAIT_CYCLE_8;
    ADC_InitStruct.ScanChannelLen = ChanleNum;
    ADC_Init(ADC0, &ADC_InitStruct);

    /* Enable ADC0 */
    ADC_Cmd(ADC0, ENABLE);

    uint32_t temp1 = 0 , temp2 = 0;
    for(int i = 0 ; i < 64 ; i++){
        ADC_StartConversion(ADC0);
        while(ADC_GetIntFlagStatus(ADC0, ADC_INT_FLAG_EOS) != SET);
        temp1 += ADC0->DR_SCAN[0];
        temp2 += ADC0->DR_SCAN[1];
        ADC_ClearIntFlag(ADC0, ADC_INT_FLAG_EOS);
    }
    charger.battery_L.current_offset = temp1 >> 6;	//充电电流偏移
    charger.battery_R.current_offset = temp2 >> 6;	//充电电流偏移

    ADCCOM_ChannelConfigStruct.Channel = BAT_L_CUR_CHANNEL;
    ADCCOM_ChannelConfigStruct.Offset = charger.battery_L.current_offset;
    ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);

    ADCCOM_ChannelConfigStruct.Channel = BAT_R_CUR_CHANNEL;
    ADCCOM_ChannelConfigStruct.Offset = charger.battery_R.current_offset;
    ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);
    
    /*停止转换*/
    ADC_StopConversion(ADC0);
    /*关闭ADC*/
    ADC_Cmd(ADC0, DISABLE);

    delay_us(5);

    /*EOS中断开启*/
    ADC_IntCmd(ADC0 , ADC_INT_TYPE_EOS , ENABLE);

    ADC0->TRIG_CR |= ADC_TRIG_SW_SEQ_CONTINUOUS_CONV;   //软件触发 序列连续扫描

    /*ADC使能*/
    ADC_Cmd(ADC0, ENABLE);
    /*开始ADC转换*/
    ADC_StartConversion(ADC0);

    /*使能中断*/
    NVIC_EnableIRQ(ADC0_IRQn);
    /*设置优先级*/
    NVIC_SetPriority(ADC0_IRQn, 1);
}

#elif(ADC_CONFIG_MODE == ADC_CONFIG_MODE1)

void adc_config(void){
    /*ADC端口配置*/
    adc_gpio_config();
    
    /* Config ADC common parameters */
    ADCCOM_StructInit(&ADCCOM_InitStruct);
    ADCCOM_InitStruct.AdcSpeed = 1;
    ADCCOM_InitStruct.Vref = ADC_VREF_AVDD;
    ADCCOM_InitStruct.ClkDiv = ADC_CLK_DIV1;
    ADCCOM_InitStruct.SampleTime0 = ADC_SAMPLE_TIME_34Cycles;
    ADCCOM_InitStruct.SampleTime1 = ADC_SAMPLE_TIME_34Cycles;
    ADCCOM_InitStruct.SampleAccuracy = ADC_Sample_Accuracy_12Bit;
    ADCCOM_InitStruct.PGASel = ADC_PGA_SEL_ALL;
    ADCCOM_Init(&ADCCOM_InitStruct);

    ADCCOM_ChannelStructInit(&ADCCOM_ChannelConfigStruct);

    ADCCOM_ChannelConfigStruct.OversampleEnable = DISABLE;
    ADCCOM_ChannelConfigStruct.SampleTimeSel = ADC_SAMPLE_TIME_SEL0;
    ADCCOM_ChannelConfigStruct.Offset = 0;

    ADCCOM_ChannelConfigStruct.Channel = BAT_L_CUR_CHANNEL;
    ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);

    ADCCOM_ChannelConfigStruct.Channel = BAT_R_CUR_CHANNEL;
    ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);

    ADCCOM_ChannelConfigStruct.Channel = BAT_L_VOL_CHANNEL;
    ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);

    ADCCOM_ChannelConfigStruct.Channel = BAT_R_VOL_CHANNEL;
    ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);

    ADCCOM_ChannelConfigStruct.Channel = PCB_TEMP_CHANNEL;
    ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);

    ADCCOM_ChannelConfigStruct.Channel = VIN_CHANNEL;
    ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);

    /* Config ADC0 */
    ADC_StructInit(&ADC_InitStruct);
    ADC_InitStruct.TrigMode = ADC_TRIG_SW_SINGLE_SEQ_CONV;  //单次扫描
    ADC_InitStruct.ContinueWait = ADC_CONTINUE_WAIT_CYCLE_32;
    ADC_InitStruct.ScanChannelLen = ChanleNum;

    ADC_ScanChannelConfig(ADC0, ADC_SCAN_Channel_0, BAT_L_CUR_CHANNEL);
    ADC_ScanChannelConfig(ADC0, ADC_SCAN_Channel_1, BAT_R_CUR_CHANNEL);
    ADC_ScanChannelConfig(ADC0, ADC_SCAN_Channel_2, BAT_L_VOL_CHANNEL);
    ADC_ScanChannelConfig(ADC0, ADC_SCAN_Channel_3, BAT_R_VOL_CHANNEL);
    ADC_ScanChannelConfig(ADC0, ADC_SCAN_Channel_4, PCB_TEMP_CHANNEL);
    ADC_ScanChannelConfig(ADC0, ADC_SCAN_Channel_5, VIN_CHANNEL);

    ADC_Init(ADC0, &ADC_InitStruct);

    ADC_ChannelConfigStruct.DataAlign = ADC_DATA_ALIGN_RIGHT;
    ADC_ChannelConfigStruct.DataSign = ADC_DATA_UNSIGNED;

    ADC_ChannelConfigStruct.Channel = BAT_L_CUR_CHANNEL;
    ADC_ChannelConfig(ADC0, &ADC_ChannelConfigStruct);

    ADC_ChannelConfigStruct.Channel = BAT_R_CUR_CHANNEL;
    ADC_ChannelConfig(ADC0, &ADC_ChannelConfigStruct);

    ADC_ChannelConfigStruct.Channel = BAT_L_VOL_CHANNEL;
    ADC_ChannelConfig(ADC0, &ADC_ChannelConfigStruct);

    ADC_ChannelConfigStruct.Channel = BAT_R_VOL_CHANNEL;
    ADC_ChannelConfig(ADC0, &ADC_ChannelConfigStruct);

    ADC_ChannelConfigStruct.Channel = PCB_TEMP_CHANNEL;
    ADC_ChannelConfig(ADC0, &ADC_ChannelConfigStruct);

    ADC_ChannelConfigStruct.Channel = VIN_CHANNEL;
    ADC_ChannelConfig(ADC0, &ADC_ChannelConfigStruct);

    /* Enable ADC0 */
    ADC_Cmd(ADC0, ENABLE);

    uint32_t temp1 = 0 , temp2 = 0;
    for(int i = 0 ; i < 64 ; i++){
        ADC_StartConversion(ADC0);
        while(ADC_GetIntFlagStatus(ADC0, ADC_INT_FLAG_EOS) != SET);
        temp1 += ADC0->DR_SCAN[0];
        temp2 += ADC0->DR_SCAN[1];
        ADC_ClearIntFlag(ADC0, ADC_INT_FLAG_EOS);
    }
    charger.battery_L.current_offset = temp1 >> 6;	//充电电流偏移
    charger.battery_R.current_offset = temp2 >> 6;	//充电电流偏移

    // ADCCOM_ChannelConfigStruct.Channel = BAT_L_CUR_CHANNEL;
    // ADCCOM_ChannelConfigStruct.Offset = charger.battery_L.current_offset;
    // ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);

    // ADCCOM_ChannelConfigStruct.Channel = BAT_R_CUR_CHANNEL;
    // ADCCOM_ChannelConfigStruct.Offset = charger.battery_R.current_offset;
    // ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);
    
    /*停止转换*/
    ADC_StopConversion(ADC0);
    /*关闭ADC*/
    ADC_Cmd(ADC0, DISABLE);

    delay_us(5);

    /*EOS中断开启*/
    ADC_IntCmd(ADC0 , ADC_INT_TYPE_EOS , ENABLE);

    // ADC0->TRIG_CR |= ADC_TRIG_SW_SEQ_CONTINUOUS_CONV;   //软件触发 序列连续扫描

    ADC_StructInit(&ADC_InitStruct);
    ADC_InitStruct.TrigMode = ADC_TRIG_SW_SEQ_CONTINUOUS_CONV;  //单次扫描
    ADC_InitStruct.ContinueWait = ADC_CONTINUE_WAIT_CYCLE_8;
    ADC_InitStruct.ScanChannelLen = ChanleNum;
    ADC_Init(ADC0, &ADC_InitStruct);

    /*使能中断*/
    NVIC_EnableIRQ(ADC0_IRQn);
    /*设置优先级*/
    NVIC_SetPriority(ADC0_IRQn, 1);

    /*ADC使能*/
    ADC_Cmd(ADC0, ENABLE);
    /*开始ADC转换*/
    ADC_StartConversion(ADC0);
}

#elif(ADC_CONFIG_MODE == ADC_CONFIG_MODE2)

/**
 * @description: ADC配置
 * @return {*}
 */
void adc_config(void){
    /*ADC端口配置*/
    adc_gpio_config();
    
    /* Config ADC common parameters */
    ADCCOM_StructInit(&ADCCOM_InitStruct);
    ADCCOM_InitStruct.AdcSpeed = 1;
    ADCCOM_InitStruct.Vref = ADC_VREF_AVDD;
    ADCCOM_InitStruct.ClkDiv = ADC_CLK_DIV1;
    ADCCOM_InitStruct.SampleTime0 = ADC_SAMPLE_TIME_34Cycles;
    ADCCOM_InitStruct.SampleTime1 = ADC_SAMPLE_TIME_34Cycles;
    ADCCOM_InitStruct.SampleAccuracy = ADC_Sample_Accuracy_12Bit;
    ADCCOM_InitStruct.IN15Sel = ADC_IN15_SEL_TEMP;
    ADCCOM_InitStruct.PGASel = ADC_PGA_SEL_ALL;
    ADCCOM_Init(&ADCCOM_InitStruct);
    ADCCOM_ChannelStructInit(&ADCCOM_ChannelConfigStruct);

    ADCCOM_ChannelConfigStruct.Channel = gADCconvertSeq[gADCconvertPos];
    ADCCOM_ChannelConfigStruct.OversampleEnable = DISABLE;
    ADCCOM_ChannelConfigStruct.SampleTimeSel = ADC_SAMPLE_TIME_SEL0;
    ADCCOM_ChannelConfigStruct.Offset = 0;
    ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);
    
    ADC_ChannelStructInit(&ADC_ChannelConfigStruct);
    ADC_ChannelConfigStruct.Channel = gADCconvertSeq[gADCconvertPos];
    ADC_ChannelConfigStruct.DataAlign = ADC_DATA_ALIGN_RIGHT;
    ADC_ChannelConfigStruct.DataSign = ADC_DATA_UNSIGNED;
    ADC_ChannelConfig(ADC0, &ADC_ChannelConfigStruct);


    /* Config ADC0 */
    ADC_StructInit(&ADC_InitStruct);
    ADC_InitStruct.TrigMode = ADC_TRIG_SW_SINGLE_CONV;  //单次转换
    ADC_InitStruct.ContinueWait = ADC_CONTINUE_WAIT_CYCLE_0;
    ADC_InitStruct.SoftTrigChannel = gADCconvertSeq[gADCconvertPos];
    ADC_Init(ADC0, &ADC_InitStruct);

    /* Enable ADC0 */
    ADC_Cmd(ADC0, ENABLE);

    uint32_t temp1 = 0 , temp2 = 0;
    for(int i = 0 ; i < 64 ; i++){
        ADC_StartConversion(ADC0);
        while(ADC_GetIntFlagStatus(ADC0, ADC_INT_FLAG_EOC) != SET);
        temp1 += ADC_GetSingleData(ADC0);
        ADC_ClearIntFlag(ADC0, ADC_INT_FLAG_EOC);
    }
    charger.battery_L.current_offset = temp1 >> 6;	//充电电流偏移

    /*停止转换*/
    ADC_StopConversion(ADC0);


    delay_us(5);
    gADCconvertPos++;
    ADC_InitStruct.SoftTrigChannel = gADCconvertSeq[gADCconvertPos];
    ADC_Init(ADC0, &ADC_InitStruct);

    for(int j = 0 ; j < 64 ; j++){
        ADC_StartConversion(ADC0);
        while(ADC_GetIntFlagStatus(ADC0, ADC_INT_FLAG_EOC) != SET);
        temp2 += ADC_GetSingleData(ADC0);
        ADC_ClearIntFlag(ADC0, ADC_INT_FLAG_EOC);
    }
    charger.battery_R.current_offset = temp2 >> 6;	//充电电流偏移

    ADCCOM_ChannelConfigStruct.Channel = BAT_L_CUR_CHANNEL;
    ADCCOM_ChannelConfigStruct.Offset = charger.battery_L.current_offset;
    ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);

    ADCCOM_ChannelConfigStruct.Channel = BAT_R_CUR_CHANNEL;
    ADCCOM_ChannelConfigStruct.Offset = charger.battery_R.current_offset;
    ADCCOM_ChannelConfig(&ADCCOM_ChannelConfigStruct);
    
    /*停止转换*/
    ADC_StopConversion(ADC0);

    gADCconvertPos = 0;
    ADC_InitStruct.SoftTrigChannel = gADCconvertSeq[gADCconvertPos];
    ADC_Init(ADC0, &ADC_InitStruct);

    delay_us(5);

    /*EOS中断开启*/
    ADC_IntCmd(ADC0 , ADC_INT_TYPE_EOC , ENABLE);

    /*ADC使能*/
    ADC_Cmd(ADC0, ENABLE);

    /*使能中断*/
    NVIC_EnableIRQ(ADC0_IRQn);
    /*设置优先级*/
    NVIC_SetPriority(ADC0_IRQn, 1);
}


#endif

